home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
oleo130s.zip
/
OLEO130S.TAR
/
oleo-1.3
/
cells.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-30
|
12KB
|
589 lines
/* Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
This file is part of Oleo, the GNU Spreadsheet.
Oleo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Oleo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Oleo; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define obstack_chunk_alloc ck_malloc
#define obstack_chunk_free free
#include "obstack.h"
#include "funcdef.h"
#include "sysdef.h"
#include "global.h"
#include "cell.h"
#include "eval.h"
#include "errors.h"
#include "lists.h"
#include "format.h"
#include "io-abstract.h"
#include "io-generic.h"
#include "io-term.h"
#include "cmd.h"
struct value
{
int type;
union vals x;
};
#define Float x.c_d
#define String x.c_s
#define Int x.c_l
#define Value x.c_i
#define Rng x.c_r
#define ERROR(x) \
{ \
p->Value=x; \
p->type=TYP_ERR;\
return; \
}
static int
cell (row, col, dowhat, p)
long row;
long col;
char *dowhat;
struct value *p;
{
struct func
{
char *name;
int typ;
};
static struct func cell_funs[] =
{
{"row", TYP_INT},
{"column", TYP_INT},
{"width", TYP_INT},
{"lock", TYP_STR},
{"protection", TYP_STR},
{"justify", TYP_STR},
{"alignment", TYP_STR},
{"fmt", TYP_STR},
{"format", TYP_STR},
{"type", TYP_STR},
{"formula", TYP_STR},
{"value", 0},
{0, 0}
};
CELL *cell_ptr;
char *strptr;
struct func *func;
struct func *f1;
int n;
n = strlen (dowhat) - 1;
f1 = 0;
for (func = cell_funs; func->name; func++)
if (func->name[0] == dowhat[0]
&& (n == 0 || !strincmp (&(func->name[1]), &dowhat[1], n)))
{
if (f1)
return BAD_INPUT;
f1 = func;
}
if (!f1)
return BAD_INPUT;
p->type = f1->typ;
switch (f1 - cell_funs)
{
case 0:
p->Int = row;
break;
case 1:
p->Int = col;
break;
case 2:
p->Int = get_width (col);
break;
case 3:
case 4:
cell_ptr = find_cell (row, col);
p->String = ( (cell_ptr ? GET_LCK (cell_ptr) : default_lock)
? "locked"
: "unlocked");
break;
case 5:
case 6:
cell_ptr = find_cell (row, col);
p->String = jst_to_str (cell_ptr ? GET_JST (cell_ptr) : default_jst);
break;
case 7:
case 8:
p->String = fmt_to_str ((cell_ptr = find_cell (row, col)) ? GET_FMT (cell_ptr) : 0);
break;
case 9:
cell_ptr = find_cell (row, col);
if (cell_ptr)
switch (GET_TYP (cell_ptr))
{
case TYP_FLT:
p->String = "float";
break;
case TYP_INT:
p->String = "integer";
break;
case TYP_STR:
p->String = "string";
break;
case TYP_BOL:
p->String = "boolean";
break;
case TYP_ERR:
p->String = "error";
break;
default:
p->String = "unknown";
}
else
p->String = "null";
break;
case 10:
cell_ptr = find_cell (row, col);
if (cell_ptr && (GET_TYP (cell_ptr) || cell_ptr->cell_formula))
{
strptr = decomp (row, col, cell_ptr);
p->String = obstack_alloc (&tmp_mem, strlen (strptr) + 1);
strcpy (p->String, strptr);
decomp_free ();
}
else
p->String = "";
break;
case 11:
cell_ptr = find_cell (row, col);
if (cell_ptr)
{
p->type = GET_TYP (cell_ptr);
p->x = cell_ptr->c_z;
}
else
p->type = 0;
break;
default:
return BAD_INPUT;
}
return 0;
}
static void
do_curcell (p)
struct value *p;
{
int tmp;
tmp = cell (curow, cucol, p->String, p);
if (tmp)
ERROR (tmp);
}
static void
do_my (p)
struct value *p;
{
int tmp;
tmp = cell (cur_row, cur_col, p->String, p);
if (tmp)
ERROR (tmp);
}
/* Note that the second argument may be *anything* including ERROR. If it is
error, we find the first occurence of that ERROR in the range */
static void
do_member (p)
struct value *p;
{
CELLREF crow;
CELLREF ccol;
int foundit;
CELL *cell_ptr;
find_cells_in_range (&(p->Rng));
while (cell_ptr = next_row_col_in_range (&crow, &ccol))
{
if (GET_TYP (cell_ptr) != (p + 1)->type)
continue;
switch ((p + 1)->type)
{
case 0:
foundit = 1;
break;
case TYP_FLT:
foundit = cell_ptr->cell_flt == (p + 1)->Float;
break;
case TYP_INT:
foundit = cell_ptr->cell_int == (p + 1)->Int;
break;
case TYP_STR:
foundit = !strcmp (cell_ptr->cell_str, (p + 1)->String);
break;
case TYP_BOL:
foundit = cell_ptr->cell_bol == (p + 1)->Value;
break;
case TYP_ERR:
foundit = cell_ptr->cell_err == (p + 1)->Value;
break;
default:
foundit = 0;
#ifdef TEST
panic ("Unknown type (%d) in member", (p + 1)->type);
#endif
}
if (foundit)
{
no_more_cells ();
p->Int = 1 + crow - p->Rng.lr + (ccol - p->Rng.lc) * (1 + p->Rng.hr - p->Rng.lr);
p->type = TYP_INT;
return;
}
}
p->Int = 0L;
p->type = TYP_INT;
}
static void
do_smember (p)
struct value *p;
{
CELLREF crow;
CELLREF ccol;
CELL *cell_ptr;
char *string;
string = (p + 1)->String;
find_cells_in_range (&(p->Rng));
while (cell_ptr = next_row_col_in_range (&crow, &ccol))
{
if (((GET_TYP (cell_ptr) == 0) && (string[0] == '\0'))
|| (cell_ptr && (GET_TYP (cell_ptr) == TYP_STR)
&& strstr (string, cell_ptr->cell_str)))
{
no_more_cells ();
p->Int = 1 + (crow - p->Rng.lr)
+ (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
p->type = TYP_INT;
return;
}
}
p->Int = 0L;
p->type = TYP_INT;
}
static void
do_members (p)
struct value *p;
{
CELLREF crow;
CELLREF ccol;
CELL *cell_ptr;
char *string;
string = (p + 1)->String;
find_cells_in_range (&(p->Rng));
while (cell_ptr = next_row_col_in_range (&crow, &ccol))
{
if (GET_TYP (cell_ptr) != TYP_STR)
continue;
if (strstr (cell_ptr->cell_str, string))
{
no_more_cells ();
p->Int = 1 + (crow - p->Rng.lr)
+ (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
p->type = TYP_INT;
return;
}
}
p->Int = 0L;
p->type = TYP_INT;
}
static void
do_pmember (p)
struct value *p;
{
CELLREF crow;
CELLREF ccol;
CELL *cell_ptr;
char *string;
string = (p + 1)->String;
find_cells_in_range (&(p->Rng));
while (cell_ptr = next_row_col_in_range (&crow, &ccol))
{
if ((GET_TYP (cell_ptr) == 0 && string[0] == '\0')
|| (cell_ptr && GET_TYP (cell_ptr) == TYP_STR && !strncmp (string, cell_ptr->cell_str, strlen (cell_ptr->cell_str))))
{
no_more_cells ();
p->Int = 1 + (crow - p->Rng.lr)
+ (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
p->type = TYP_INT;
return;
}
}
p->Int = 0L;
p->type = TYP_INT;
}
static void
do_memberp (p)
struct value *p;
{
CELLREF crow;
CELLREF ccol;
CELL *cell_ptr;
int tmp;
char *string;
string = (p + 1)->String;
find_cells_in_range (&(p->Rng));
tmp = strlen (string);
while (cell_ptr = next_row_col_in_range (&crow, &ccol))
{
if (GET_TYP (cell_ptr) != TYP_STR)
continue;
if (!strncmp (cell_ptr->cell_str, string, tmp))
{
no_more_cells ();
p->Int = 1 + (crow - p->Rng.lr)
+ (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
p->type = TYP_INT;
return;
}
}
p->Int = 0L;
p->type = TYP_INT;
}
static void
do_hlookup (p)
struct value *p;
{
struct rng *rng = &((p)->Rng);
double fltval = (p + 1)->Float;
long offset = (p + 2)->Int;
CELL *cell_ptr;
double f;
CELLREF col;
CELLREF row;
char *strptr;
row = rng->lr;
for (col = rng->lc; col <= rng->hc; col++)
{
if (!(cell_ptr = find_cell (row, col)))
ERROR (NON_NUMBER);
switch (GET_TYP (cell_ptr))
{
case TYP_FLT:
if (fltval < cell_ptr->cell_flt)
goto out;
break;
case TYP_INT:
if (fltval < cell_ptr->cell_int)
goto out;
break;
case TYP_STR:
strptr = cell_ptr->cell_str;
f = astof (&strptr);
if (!*strptr && fltval > f)
goto out;
else
ERROR (NON_NUMBER);
case 0:
case TYP_BOL:
case TYP_ERR:
default:
ERROR (NON_NUMBER);
}
}
out:
if (col == rng->lc)
ERROR (OUT_OF_RANGE);
--col;
row = rng->lr + offset;
if (row > rng->hr)
ERROR (OUT_OF_RANGE);
cell_ptr = find_cell (row, col);
if (!cell_ptr)
{
p->type = 0;
p->Int = 0;
}
else
{
p->type = GET_TYP (cell_ptr);
p->x = cell_ptr->c_z;
}
}
static void
do_vlookup (p)
struct value *p;
{
struct rng *rng = &((p)->Rng);
double fltval = (p + 1)->Float;
long offset = (p + 2)->Int;
CELL *cell_ptr;
double f;
CELLREF col;
CELLREF row;
char *strptr;
col = rng->lc;
for (row = rng->lr; row <= rng->hr; row++)
{
if (!(cell_ptr = find_cell (row, col)))
ERROR (NON_NUMBER);
switch (GET_TYP (cell_ptr))
{
case TYP_FLT:
if (fltval < cell_ptr->cell_flt)
goto out;
break;
case TYP_INT:
if (fltval < cell_ptr->cell_int)
goto out;
break;
case TYP_STR:
strptr = cell_ptr->cell_str;
f = astof (&strptr);
if (!*strptr && fltval > f)
goto out;
else
ERROR (NON_NUMBER);
case 0:
case TYP_BOL:
case TYP_ERR:
default:
ERROR (NON_NUMBER);
}
}
out:
if (row == rng->lr)
ERROR (OUT_OF_RANGE);
--row;
col = rng->lc + offset;
if (col > rng->hc)
ERROR (OUT_OF_RANGE);
cell_ptr = find_cell (row, col);
if (!cell_ptr)
{
p->type = 0;
p->Int = 0;
}
else
{
p->type = GET_TYP (cell_ptr);
p->x = cell_ptr->c_z;
}
}
static void
do_vlookup_str (p)
struct value *p;
{
struct rng *rng = &((p)->Rng);
char * key = (p + 1)->String;
long offset = (p + 2)->Int;
CELL *cell_ptr;
CELLREF col;
CELLREF row;
col = rng->lc;
for (row = rng->lr; row <= rng->hr; row++)
{
if (!(cell_ptr = find_cell (row, col)))
ERROR (NON_NUMBER);
switch (GET_TYP (cell_ptr))
{
case TYP_STR:
if (!strcmp (key, cell_ptr->cell_str))
goto out;
break;
case 0:
case TYP_FLT:
case TYP_INT:
case TYP_BOL:
case TYP_ERR:
default:
ERROR (NON_NUMBER);
}
}
out:
if (row > rng->hr)
ERROR (OUT_OF_RANGE);
col = rng->lc + offset;
if (col > rng->hc)
ERROR (OUT_OF_RANGE);
cell_ptr = find_cell (row, col);
if (!cell_ptr)
{
p->type = 0;
p->Int = 0;
}
else
{
p->type = GET_TYP (cell_ptr);
p->x = cell_ptr->c_z;
}
}
static void
do_cell (p)
struct value *p;
{
int tmp;
tmp = cell (p->Int, (p + 1)->Int, (p + 2)->String, p);
if (tmp)
ERROR (tmp);
}
struct function cells_funs[] =
{
{C_FN1 | C_T, X_A1, "S", do_curcell, "curcell"},
{C_FN1 | C_T, X_A1, "S", do_my, "my"},
{C_FN3 | C_T, X_A3, "IIS", do_cell, "cell"},
{C_FN2, X_A2, "RA", do_member, "member"},
{C_FN2, X_A2, "RS", do_smember, "smember"},
{C_FN2, X_A2, "RS", do_members, "members"},
{C_FN2, X_A2, "RS", do_pmember, "pmember"},
{C_FN2, X_A2, "RS", do_memberp, "memberp"},
{C_FN3, X_A3, "RFI", do_hlookup, "hlookup"},
{C_FN3, X_A3, "RFI", do_vlookup, "vlookup"},
{C_FN3, X_A3, "RSI", do_vlookup_str, "vlookup_str"},
{0, 0, "", 0, 0},
};